(module mp22-soln
  (lib "eopl.ss" "eopl")
  
  (require "drscheme-init.scm") 
  
  (define lex0
    '((whitespace (whitespace)            skip)
      (number     (digit (arbno digit)) number)
      (Times-op   ("*")     string)
      (Div-op     ("/")     string)
      (Plus-op    ("+")     string)
      (Diff-op    ("-")     string)       
      
      )
    )

  
  (define Arith-grammar
    '(
      (AExp
       (operator "(" AExp (arbno "," AExp ) ")")
       Composite-Exp)
      (AExp
       (number)
       const-AExp)
      (operator
       (Times-op)
       Times-oper)
      (operator
       (Plus-op)
       Plus-oper)
      (operator
       (Diff-op)
       Diff-oper)
      (operator
       (Div-op)
       Div-oper)
      )
    )

  ;; build a scanner with empty grammar 
  (define scan0 (sllgen:make-string-scanner lex0 '()))
  
  ;; build data-types
  (sllgen:make-define-datatypes lex0 Arith-grammar)
  
  ;; build scanner with grammar 
  (define just-scan
    (sllgen:make-string-scanner lex0 Arith-grammar))
  
  ;; build parser 
  (define scan&parse 
    (sllgen:make-string-parser lex0 Arith-grammar))
  
  ;; show the datatypes 
  (define show-the-datatypes 
    (lambda () (sllgen:show-define-datatypes lex0 Arith-grammar)))
  
  (define exp1 "22")
  
  
  
;;value-of-aexp: AExp ==> number
;;usage: (value-of-aexp aexp)
;;purpose: Given a syntaxt tree produced by the above mentioned Grammar , 
  ;;this preocedure evaluates the arithmatic expression that is part of this Syntax Tree

(define value-of-aexp
    (lambda(aexp)
      (cases AExp aexp
        (const-AExp(n) n)
        (Composite-Exp(op ex1 lst-ex2)
            (cond
              ((null? lst-ex2) ((oper? op) (value-of-aexp ex1)))
              (else
               (val-help  op ex1 lst-ex2))
              )
            )
      )
    )
  )

  
  (define val-help
    (lambda (op exp1 lst-exp2)
      ;;(cond
      ;;  ((null? lst-exp2) (value-of-aexp exp1))
      ;;  (else
      (cases AExp exp1
        (const-AExp(n1)
                   (cond 
                     ((null? lst-exp2) n1)
                     (else 
                      (val-help 
                       op 
                       ((oper? op) n1 (value-of-aexp (car lst-exp2)))
                       (cdr lst-exp2)
                       )
                      )
                     )
                   )
        (Composite-Exp(op e1 l-e2)
                      (val-help 
                       op 
                       ((oper? op)
                        (value-of-aexp exp1)
                        (value-of-aexp (car lst-exp2))
                        )
                       (cdr lst-exp2)
                       )
                      )
        ;;   )
        ;; )
        )
      )
    )
  
                                    
  
;;oper?: operator ==> operator-symbol
;;usage:(oper? op)
;;purpose: Given an instance of the  datatype operator ,  
;; this procedure returns the  actual operator for that data-structure.
  
(define oper?
  (lambda (op)
   (cases operator op
                         (Times-oper (Tio) *)
                         (Plus-oper (plo)  +)
                         (Diff-oper (Difo) -)
                         (Div-oper (Divo)  /)
                         )
   )
  )
(define to (Times-oper "*"))                        
(define po (Plus-oper "*"))
(define dfo (Diff-oper "*"))
(define dio (Div-oper "*")) 
  

  
  
;;value-of-aexp-string: string ==> number
;;usage:(value-of-aexp-string str)
;;purpose:Gievn a sting which has a Arithmetic Expression , 
;;  this  will convert that into an Arithmetic syntax tree and 
;;  then Evaluate the generated tree using the value-of-aexp procedure.
;;examples:  
;;(value-of-aexp-string "*(/(+(2,4) , 2), /(10,2))") ==> 15  
;;(value-of-aexp-string "*(2, /(10,2))") ==> 10
;;;(value-of-aexp-string "*(2, +(3,2))") ==> 10
;;; (value-of-aexp-string "22") ==> 22
(define value-of-aexp-string 
 (lambda(str)
   (value-of-aexp (scan&parse str)
                  )
   )
  )
  
               
  
  )